package study.week03.gateway_final.inbound;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.internal.StringUtil;
import study.week03.gateway_final.filter.CustomHttpFilter;
import study.week03.gateway_final.outbound.OutboundHandler;
import study.week03.gateway_final.router.CustomRouter;
import study.week03.uti.HttpClientUtil;

import java.nio.charset.StandardCharsets;
import java.util.List;

import static io.netty.handler.codec.http.HttpHeaderNames.CONNECTION;
import static io.netty.handler.codec.http.HttpHeaderValues.KEEP_ALIVE;
import static io.netty.handler.codec.http.HttpResponseStatus.NO_CONTENT;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;

public class InboundHandler extends ChannelInboundHandlerAdapter {
    private CustomHttpFilter[] filterChain ;
    private List<String> serverList;
    CustomRouter router;
    private OutboundHandler outboundHandler;
    public InboundHandler(CustomHttpFilter[] filterChain, List<String> serverList, CustomRouter router) {
        this.filterChain = filterChain;
        this.serverList = serverList;
        this.router = router;
        this.outboundHandler = new OutboundHandler(filterChain,serverList,router);
    }
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        try {
            FullHttpRequest fullRequest = (FullHttpRequest) msg;
            for (int i = 0; i < filterChain.length; i++) {
               if(!filterChain[i].inbound(fullRequest,ctx)){
                   //返回false就结束请求
                   inboundRefuse(fullRequest,ctx);
                   return ;
               }
            }
           outboundHandler.execute(ctx,fullRequest);
        } catch(Exception e) {
            e.printStackTrace();
        } finally {
            ReferenceCountUtil.release(msg);
        }
    }

    /**
     * 过滤器链拒绝请求时的统一处理
     * @param fullRequest
     * @param ctx
     */
    private void inboundRefuse(FullHttpRequest fullRequest, ChannelHandlerContext ctx) {
        FullHttpResponse response = null;
        try {
            String body = "inbound filter refuse.";

            response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(body.getBytes(StandardCharsets.UTF_8)));
            response.headers().set("Content-Type", "application/json");
            response.headers().setInt("Content-Length", response.content().readableBytes());

        } catch (Exception e) {
            System.out.println("处理出错:"+e.getMessage());
            response = new DefaultFullHttpResponse(HTTP_1_1, NO_CONTENT);
        } finally {
            if (fullRequest != null) {
                if (!HttpUtil.isKeepAlive(fullRequest)) {
                    ctx.write(response).addListener(ChannelFutureListener.CLOSE);
                } else {
                    response.headers().set(CONNECTION, KEEP_ALIVE);
                    ctx.write(response);
                }
                ctx.flush();
            }
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }

}
